home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
fortran
/
ftnchk26.zip
/
SOURCE
/
PRSYMTAB.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-09-19
|
49KB
|
1,839 lines
/* prsymtab.c:
Routines associated with printing of symbol table info
Copyright (C) 1992 by Robert K. Moniot.
This program is free software. Permission is granted to
modify it and/or redistribute it, retaining this notice.
No guarantees accompany this software.
Shared functions defined:
arg_array_cmp() Compares subprogram calls with defns.
check_arglists() Scans global symbol table for subprograms
and finds subprogram defn if it exists.
check_comlists() Scans global symbol table for common blocks.
com_cmp_strict() Compares lists of common variables.
debug_symtabs() Prints debugging info about symbol tables.
print_loc_symbols(curmodhash) Prints local symtab info.
Private functions defined:
check_mixed_common() checks common for nonportable mixed type
sort_symbols() Sorts the list of names of a given category.
swap_symptrs() Swaps a pair of pointers.
check_flags() Outputs messages about used-before-set etc.
print_symbols(sym_list,n,do_types) Prints symbol lists.
print_variables(sym_list,n) Prints variable symbol table
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "ftnchek.h"
#include "symtab.h"
PRIVATE int
has_nonalnum();
PRIVATE unsigned
find_sixclashes(), print_variables(), print_symbols();
PRIVATE void
swap_symptrs(), sort_symbols(), check_flags(), check_mixed_common(),
com_cmp_lax(),com_cmp_strict(), arg_array_cmp(),
print_tokenlist(), visit_child(), sort_child_list();
/* Shorthand for check control settings */
#define check_array_dims (array_arg_check&01) /* levels 1 and 3 */
#define check_array_size (array_arg_check&02) /* levels 2 and 3 */
#define check_set_used (usage_check&01) /* levels 1 and 3 */
#define check_unused (usage_check&02) /* levels 2 and 3 */
#define pluralize(n) ((n)==1? "":"s") /* singular/plural suffix for n */
#define CMP_ERR_LIMIT 3 /* stop printing errors after this many */
PRIVATE void
arg_array_cmp(name,args1,args2)
/* Compares subprogram calls with definition */
char *name;
ArgListHeader *args1, *args2;
{
int i,
typerr = 0,
usage_err = 0;
int n,
n1 = args1->numargs,
n2 = args2->numargs;
ArgListElement *a1 = args1->arg_array,
*a2 = args2->arg_array;
n = (n1 > n2) ? n2: n1; /* n = min(n1,n2) */
if (n1 != n2){
fprintf(list_fd,"\nSubprogram %s: varying number of arguments:",name);
fprintf(list_fd,"\n\t%s with %d argument%s in module %s line %u file %s",
args1->is_defn? "Defined":"Invoked",
n1,pluralize(n1),
args1->module->name,
args1->line_num,
args1->filename);
fprintf(list_fd,"\n\t%s with %d argument%s in module %s line %u file %s",
args2->is_defn? "Defined":"Invoked",
n2,pluralize(n2),
args2->module->name,
args2->line_num,
args2->filename);
}
{ /* Look for type mismatches */
typerr = 0;
for (i=0; i<n; i++) {
if(a1[i].type != a2[i].type){
int t1 = datatype_of(a1[i].type),
t2 = datatype_of(a2[i].type);
/* Allow hollerith to match integer or logical */
if( (t1 == type_HOLLERITH
&& (t2 == type_INTEGER || t2 == type_LOGICAL))
|| (t2 == type_HOLLERITH
&& (t1 == type_INTEGER || t1 == type_LOGICAL))
&& (storage_class_of(a1[i].type)==storage_class_of(a1[i].type)) )
continue;
/* stop after limit: probably a cascade */
if(++typerr > CMP_ERR_LIMIT) {
fprintf(list_fd,"\n etc...");
break;
}
if(typerr == 1)
fprintf(list_fd,"\nSubprogram %s: argument data type mismatch",
name);
fprintf(list_fd, "\n at position %d:", i+1);
fprintf(list_fd,"\n\t%s %s %s in module %s line %u file %s",
args1->is_defn? "Dummy type": "Actual type",
type_name[t1],
class_name[storage_class_of(a1[i].type)],
args1->module->name,
args1->line_num,
args1->filename);
fprintf(list_fd,"\n\t%s %s %s in module %s line %u file %s",
args2->is_defn? "Dummy type": "Actual type",
type_name[t2],
class_name[storage_class_of(a2[i].type)],
args2->module->name,
args2->line_num,
args2->filename);
if(args1->is_defn
&& storage_class_of(a1[i].type) == class_SUBPROGRAM
&& storage_class_of(a2[i].type) != class_SUBPROGRAM
&& datatype_of(a1[i].type) != type_SUBROUTINE
&& ! a1[i].declared_external )
fprintf(list_fd,"\n\t(possibly it is an array which was not declared)");
}
}
}/* end look for type mismatches */
/* Check arrayness of args only if defn exists */
if( args1->is_defn ) {
int arrayness_errs = 0;
unsigned long diminfo1,diminfo2,dims1,dims2,size1,size2;
for (i=0; i<n; i++) {
if(storage_class_of(a1[i].type) == class_VAR
&& storage_class_of(a2[i].type) == class_VAR) {
/* Allow holleriths to match arrays. Type
match was checked above, so they will
be matching arrays of integer or logical. */
if( datatype_of(a1[i].type) == type_HOLLERITH
|| datatype_of(a2[i].type) == type_HOLLERITH )
continue;
diminfo1 = a1[i].info.array_dim;
diminfo2 = a2[i].info.array_dim;
dims1 = array_dims(diminfo1);
dims2 = array_dims(diminfo2);
size1 = array_size(diminfo1);
size2 = array_size(diminfo2);
#if DEBUG_PRSYMTAB
if(debug_latest){
fprintf(list_fd,"\n%s arg %d: array_var=%d%d array_element=%d%d",
name,i+1,
a1[i].array_var,a2[i].array_var,
a1[i].array_element,a2[i].array_element);
fprintf(list_fd,"\nDummy dims=%ld size=%ld",dims1,size1);
fprintf(list_fd,"\nActual dims=%ld size=%ld",dims2,size2);
}
#endif
if( a1[i].array_var ) { /* I. Dummy arg is array */
if( a2[i].array_var ) {
if( a2[i].array_element ) {
/* A. Actual arg is array elt */
/* Warn on check_array_dims. */
if(check_array_dims) {
/* stop after limit: probably a cascade */
if(++arrayness_errs > CMP_ERR_LIMIT) {
fprintf(list_fd,"\n etc...");
break;
}
if(arrayness_errs == 1)
fprintf(list_fd,"\nSubprogram %s: argument arrayness mismatch",
name);
fprintf(list_fd, "\n at position %d:", i+1);
fprintf(list_fd,
"\n\tDummy arg is whole array in module %s line %u file %s",
args1->module->name,
args1->line_num,
args1->filename);
fprintf(list_fd,
"\n\tActual arg is array element in module %s line %u file %s",
args2->module->name,
args2->line_num,
args2->filename);
}
}
else {
/* B. Actual arg is whole array */
/* Warn if dims or sizes differ */
/* size = 0 or 1 means adjustable: OK to differ */
if( (check_array_size &&
(size1 > 1 && size2 > 1 && size1 != size2))
|| (check_array_dims &&
(dims1 != dims2)) ) {
/* stop after limit: probably a cascade */
if(++arrayness_errs > CMP_ERR_LIMIT) {
fprintf(list_fd,"\n etc...");
break;
}
if(arrayness_errs == 1)
fprintf(list_fd,"\nSubprogram %s: argument arrayness mismatch",
name);
fprintf(list_fd, "\n at position %d:", i+1);
fprintf(list_fd,
"\n\tDummy arg %ld dim%s size %ld in module %s line %u file %s",
dims1,pluralize(dims1),
size1,
args1->module->name,
args1->line_num,
args1->filename);
fprintf(list_fd,
"\n\tActual arg %ld dim%s size %ld in module %s line %u file %s",
dims2,pluralize(dims2),
size2,
args2->module->name,
args2->line_num,
args2->filename);
}
}
}
else {
/* C. Actual arg is scalar */
/* Warn in all cases */
/* stop after limit: probably a cascade */
if(++arrayness_errs > CMP_ERR_LIMIT) {
fprintf(list_fd,"\n etc...");
break;
}
if(arrayness_errs == 1)
fprintf(list_fd,"\nSubprogram %s: argument arrayness mismatch",
name);
fprintf(list_fd, "\n at position %d:", i+1);
fprintf(list_fd,
"\n\tDummy arg is array in module %s line %u file %s",
args1->module->name,
args1->line_num,
args1->filename);
fprintf(list_fd,
"\n\tActual arg is scalar in module %s line %u file %s",
args2->module->name,
args2->line_num,
args2->filename);